﻿using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using AModel.Generador.Servicios;
using AModel.Generador.Dominio.Entidades;
using AModel.Generador.Dominio.Funciones;
using AModel.Generador.Dominio.ClasesSistema;
using AModel.Generador.Dominio.Relaciones;
using AModel.Generador.Dominio.Paquete;

namespace AModel.Generador.ServiciosTest
{
    [TestClass]
    public class ServicioClasesTest_Clases
    {


        const String NombreClase1 = "NombreClase1fefef";
        const String NombreClase2 = "NombreClase1asdf";

        const String NombreInterfaz1 = "NombreInterfaz1";

        ServicioClases servicio;

        private void inicilizar() {
           servicio = new ServicioClases();
           servicio.CrearNuevaClase(NombreClase1);
        }


        private void inicilizarParaRelaciones()
        {
            servicio = new ServicioClases();
            servicio.CrearNuevaClase(NombreClase1);
            servicio.CrearNuevaClase(NombreClase2);
        }


#region "pruebas para una clase"
        [TestMethod]
        public void CrearNuevaClase()
        {
            ServicioClases servCrearNuevaClase = new ServicioClases();
            Clase nuevaClase = servCrearNuevaClase.CrearNuevaClase(NombreClase1);
            Assert.AreEqual(true, nuevaClase != null);
        }

        [TestMethod]
        public void GetClase()
        {
            inicilizar();
            Clase claseEditada = servicio.Obtener(NombreClase1);
            Assert.AreEqual(true, claseEditada != null);
        }

        [TestMethod]
        public void AgregarAtributoEntero()
        {
            const String NombreAtributo = "atributo_abx";
            inicilizar();
            servicio.AgregarAtributo(NombreClase1, new Entero(NombreAtributo));
            Clase claseEditada = servicio.Obtener(NombreClase1);
            bool tipoIgual = claseEditada.Atributos[NombreAtributo].GetType().Equals((new Entero(NombreAtributo).GetType()));
            Assert.AreEqual(true, tipoIgual);
        }


        [TestMethod]
        public void AgregarAtributoCadena()
        {
            const String NombreAtributo = "atributo_abx";
            inicilizar();
            servicio.AgregarAtributo(NombreClase1, new Cadena(NombreAtributo));
            Clase claseEditada = servicio.Obtener(NombreClase1);
            bool tipoIgual = claseEditada.Atributos[NombreAtributo].GetType().Equals((new Cadena(NombreAtributo).GetType()));
            Assert.AreEqual(true, tipoIgual);
        }

        [TestMethod]
        public void AgregarAtributoFecha()
        {
            const String NombreAtributo = "atributo_abx";
            inicilizar();
            servicio.AgregarAtributo(NombreClase1, new Fecha(NombreAtributo));
            Clase claseEditada = servicio.Obtener(NombreClase1);
            bool tipoIgual = claseEditada.Atributos[NombreAtributo].GetType().Equals((new Fecha(NombreAtributo).GetType()));
            Assert.AreEqual(true, tipoIgual);
        }


        [TestMethod]
        public void CrearClasesRepetidas()
        {
            inicilizar();
            Clase claseEditada = servicio.Obtener(NombreClase1);
            Clase nuevaClase = servicio.CrearNuevaClase(NombreClase1);

            Assert.AreEqual(true, nuevaClase.Equals(claseEditada));
        }

#endregion


        #region "funciones"

        [TestMethod]
        public void AgregarFuncion()
        {
            inicilizar();
            Clase claseEditada = servicio.Obtener(NombreClase1);
            Funcion nuevaFuncion = new Funcion("NuevaFuncion");
            claseEditada.Funciones.Add(nuevaFuncion);
            Assert.AreEqual(true, claseEditada.Funciones.Count == 1);
        }


        public void AgregarFuncionDevolverResultadoClase()
        {
            inicilizar();
            Clase claseEditada = servicio.Obtener(NombreClase1);
            Funcion nuevaFuncion = new Funcion("Funcion1");
            nuevaFuncion.Resultado = new Nulo("Nulo");
            claseEditada.Funciones.Add(nuevaFuncion);
            Assert.AreEqual(true, claseEditada.Funciones.Count == 1);
        }

        public void AgregarFuncionDevolverResultadoEscalar()
        {
            inicilizar();
            Clase claseEditada = servicio.Obtener(NombreClase1);
            Funcion nuevaFuncion = new Funcion("Funcion1");
            nuevaFuncion.Resultado = new Fecha("resultado");
            Assert.AreEqual(true, claseEditada.Funciones.Count == 1);
        }

        public void AgregarFuncionDevolverResultadoEscalarConParametros()
        {
            inicilizar();
            Clase claseEditada = servicio.Obtener(NombreClase1);
            Funcion nuevaFuncion = new Funcion("Funcion1");
            nuevaFuncion.Resultado = new Fecha("resultado");

            Parametro parametro1 = new Parametro("Parametro1");
            parametro1.Tipo = claseEditada;
            Parametro parametro2 = new Parametro("Parametro2");
            parametro1.Tipo = new Entero("Entro");

            nuevaFuncion.Parametros.Add(parametro1);
            nuevaFuncion.Parametros.Add(parametro2);

            Assert.AreEqual(2, claseEditada.Funciones["Funcion1"].Parametros.Count);
        }
        #endregion

        #region "Relaciones"

        [TestMethod]
        public void AgregarRelacionUnoAUno()
        {
            inicilizarParaRelaciones();

            Clase claseA = servicio.Obtener(NombreClase1);
            Clase claseB = servicio.Obtener(NombreClase2);

            servicio.registrarRelacíon(new AsociacionUnoAUno("Rel1", claseA, claseB, "claseB", "claseA"));
            Assert.AreEqual("Rel1", claseA.Relaciones["Rel1"].Nombre);
            Assert.AreEqual(1, claseA.Relaciones.Count);
        }

        [TestMethod]
        public void AgregarRelacionUnoEne()
        {
            inicilizarParaRelaciones();

            Clase claseA = servicio.Obtener(NombreClase1);
            Clase claseB = servicio.Obtener(NombreClase2);
            servicio.registrarRelacíon(new AsociacionUnoAEne("Rel1", claseA, claseB, "claseB", "claseA"));
            Assert.AreEqual("Rel1", claseA.Relaciones["Rel1"].Nombre);
            Assert.AreEqual(1, claseA.Relaciones.Count);
        }

        [TestMethod]
        public void AgregarRelacionEneAEne()
        {
            inicilizarParaRelaciones();
            Clase claseA = servicio.Obtener(NombreClase1);
            Clase claseB = servicio.Obtener(NombreClase2);

            servicio.registrarRelacíon(new AsociacionUnoAEne("Rel1", claseA, claseB, "claseB", "claseA"));
            Assert.AreEqual("Rel1", claseA.Relaciones["Rel1"].Nombre);
            Assert.AreEqual(1, claseA.Relaciones.Count);

        }

        [TestMethod]
        public void CrearInterfaz()
        {
            ServicioClases servCrearNuevaClase = new ServicioClases();
            Interfaz nuevaIntefaz = servCrearNuevaClase.CrearInterfaz(NombreClase1);
            Assert.AreEqual(true, nuevaIntefaz != null);
        }

        [TestMethod]
        public void ImplementarInterfaz()
        {

            inicilizarParaRelaciones();
            Clase claseA = servicio.Obtener(NombreClase1);
            Interfaz nuevaIntefaz = servicio.CrearInterfaz("Inf23");
            servicio.registrarRelacíon(new Implementacion("Rel1", claseA, nuevaIntefaz, "", ""));
            Assert.AreEqual(true, claseA.Relaciones.Count == 1);
        }


        [TestMethod]
        public void CrearHerencia()
        {
            inicilizarParaRelaciones();
            Clase claseA = servicio.Obtener(NombreClase1);
            Clase claseB = servicio.Obtener(NombreClase2);
            servicio.registrarRelacíon(new Herencia("Rel1", claseA, claseB, "a", "b"));
            Assert.AreEqual(true, claseA.Relaciones.Count == 1);
        }

        #endregion

        public void RenombrarClase()
         {
             const String NombreClaseNuev = "atributo_abx";
             inicilizar();
             servicio.Renombrar(NombreClase1, NombreClaseNuev);
             Clase claseEditada = servicio.Obtener(NombreClaseNuev);
             Assert.AreEqual(true, claseEditada !=  null);
         }

         public void ClonarClase()
         {            

             const String NombreClaseClon = "Clon";

             inicilizar();
             servicio.AgregarAtributo(NombreClase1, new Entero("ab ") );
             servicio.AgregarAtributo(NombreClase1, new Cadena("cf"));
             servicio.AgregarAtributo(NombreClase1, new Fecha("ab"));
             Clase claseClonada = servicio.Clonar(NombreClase1, NombreClaseClon);

             Assert.AreEqual(true, servicio.Obtener(NombreClase1).Equals(claseClonada));
         }

        
        [TestMethod]
        public void CrearPaquete()
        {
            inicilizar();
            Paquete pack = servicio.registrarPaquete("nombrePaquete");
            Assert.AreNotEqual(null, pack);
        }

        [TestMethod]
        public void CrearSubPaquete()
        {
            inicilizar();
            Paquete pack1 = servicio.registrarPaquete("nombrePaquetef1");
            Paquete pack2 = servicio.registrarPaquete("nombrePaquetee2");

            servicio.AgregarAPaquete(pack2, pack1);

            Assert.AreEqual( 1, pack1.SubPaquetes.Count);
        }
        [TestMethod]
        public void AgregarClaseAPaquete()
        {
            inicilizar();
            Paquete pack1 = servicio.registrarPaquete("nombrePaquete1");
            Clase claseA = servicio.Obtener(NombreClase1);

            servicio.AgregarAPaquete(pack1, claseA);

            Assert.AreEqual(1, pack1.Elementos.Count);
        }
    }
}
